﻿using System;
using System.Collections.Generic;
using System.Linq;
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Electrical;
using YArchitech.Revit;
using YArchitech.Revit.Electric.Common;

namespace HYCableTrayConnection
{
	internal class HYElbowConnection
	{
		public HYElbowConnection(Document m_doc, HYCableTray<CableTray> ct1, HYCableTray<CableTray> ct2)
		{
			this.doc = m_doc;
			this.horizontalCableTray = ct1;
			this.verticalCableTray = ct2;
		}

		public bool NewVerticalElbowFitting()
		{
			IList<Connector> appropriateConnector = this.horizontalCableTray.GetAppropriateConnector(this.verticalCableTray.CableTray);
			Connector connector = appropriateConnector[0];
			Connector connector2 = appropriateConnector[1];
			if (connector == null || connector2 == null || connector.IsConnected || connector2.IsConnected)
			{
				throw new MyException("桥架已经连接");
			}
			Connector otherConnector = Common.GetOtherConnector(this.horizontalCableTray, connector);
			Connector otherConnector2 = Common.GetOtherConnector(this.verticalCableTray, connector2);
			VerticalCableTrayFittingType elbowFittingType = this.GetElbowFittingType(connector, connector2, otherConnector2);
			FamilySymbol verticalCableTrayFittingType = CableTrayFitingSel.GetVerticalCableTrayFittingType(this.doc, elbowFittingType, this.horizontalCableTray);
			FamilyInstance fitting = this.NewElbowFitting(elbowFittingType, verticalCableTrayFittingType);
			this.RotateElbowFitting(connector, otherConnector, fitting);
			HYCableTray<CableTray> hycableTray;
			HYCableTray<CableTray> hycableTray2;
			if (this.horizontalCableTray.CableTray.Width > this.verticalCableTray.CableTray.Width)
			{
				hycableTray = this.horizontalCableTray;
				hycableTray2 = this.verticalCableTray;
			}
			else
			{
				hycableTray = this.verticalCableTray;
				hycableTray2 = this.horizontalCableTray;
			}
			double width = hycableTray.CableTray.Width;
			double height = hycableTray.CableTray.Height;
			hycableTray.CableTray.GetParameter(BuiltInParameter.RBS_CABLETRAY_WIDTH_PARAM).Set(hycableTray2.CableTray.Width);
			hycableTray.CableTray.GetParameter(BuiltInParameter.RBS_CABLETRAY_HEIGHT_PARAM).Set(hycableTray2.CableTray.Height);
			this.doc.Regenerate();
			this.SetFittingParams(hycableTray2, fitting, elbowFittingType);
			this.TranslationElbowFitting(connector2, otherConnector2, fitting);
			this.ElbowConnect(fitting);
			Common.RefreshModel(this.doc, fitting);
			hycableTray.CableTray.GetParameter(BuiltInParameter.RBS_CABLETRAY_WIDTH_PARAM).Set(width);
			hycableTray.CableTray.GetParameter(BuiltInParameter.RBS_CABLETRAY_HEIGHT_PARAM).Set(height);
			this.doc.Regenerate();
			return true;
		}

		private VerticalCableTrayFittingType GetElbowFittingType(Connector horizontalConnector, Connector verticalConnector, Connector otherVerticalConnector)
		{
			VerticalCableTrayFittingType result;
			if (otherVerticalConnector.Origin.Z > horizontalConnector.Origin.Z)
			{
				result = this.JudgeElbowType(horizontalConnector, verticalConnector, true);
			}
			else
			{
				result = this.JudgeElbowType(horizontalConnector, verticalConnector, false);
			}
			return result;
		}

		private VerticalCableTrayFittingType JudgeElbowType(Connector horizontalConnector, Connector verticalConnector, bool isUp)
		{
			XYZ basisZ = horizontalConnector.CoordinateSystem.BasisZ;
			XYZ xyz = -verticalConnector.CoordinateSystem.BasisY;
			double num = basisZ.AngleOnPlaneTo(xyz, XYZ.BasisZ);
			VerticalCableTrayFittingType result = VerticalCableTrayFittingType.Undefined;
			if (Math.Abs(Math.PI*.5 - num) < 0.001)
			{
				if (isUp)
				{
					result = VerticalCableTrayFittingType.LeftDownSideElbow;
				}
				else
				{
					result = VerticalCableTrayFittingType.LeftUpSideElbow;
				}
			}
			else if (Math.Abs(4.71238898038469 - num) < 0.001)
			{
				if (isUp)
				{
					result = VerticalCableTrayFittingType.RightDownSideElbow;
				}
				else
				{
					result = VerticalCableTrayFittingType.RightUpSideElbow;
				}
			}
			return result;
		}

		private FamilyInstance NewElbowFitting(VerticalCableTrayFittingType type, FamilySymbol fittingType)
		{
			XYZ lineProject = this.horizontalCableTray.GetLineProject(this.verticalCableTray.EndXYZ);
			UnifiedModified.ActivateFamilySymbol(fittingType);
			FamilyInstance result = this.doc.Create.NewFamilyInstance(lineProject, fittingType, 0);
			this.doc.Regenerate();
			return result;
		}

		private void SetFittingParams(HYCableTray<CableTray> fittingTray, FamilyInstance fitting, VerticalCableTrayFittingType type)
		{
			Dictionary<Connector, CableTrayFittingSizeParamer> fittingRelevantParamer = FittingConnectorRelevantParamer.GetFittingRelevantParamer(type, fitting);
			fittingRelevantParamer.First<KeyValuePair<Connector, CableTrayFittingSizeParamer>>().Key.Width = fittingTray.CableTray.Width;
			fittingRelevantParamer.First<KeyValuePair<Connector, CableTrayFittingSizeParamer>>().Key.Height = fittingTray.CableTray.Height;
			ElementId elementId = this.horizontalCableTray.CableTray.GetParameter(BuiltInParameter.RBS_START_LEVEL_PARAM).AsElementId();
			double num = (this.doc.GetElementById(elementId) as Level).GetParameter(BuiltInParameter.LEVEL_ELEV).AsDouble();
			double num2 = this.horizontalCableTray.CableTray.get_Parameter(BuiltInParameter.RBS_OFFSET_PARAM).AsDouble() + num;
			fitting.get_Parameter(BuiltInParameter.INSTANCE_FREE_HOST_OFFSET_PARAM).Set(num2);
			this.doc.Regenerate();
		}

		private void ElbowConnect(FamilyInstance fitting)
		{
			IList<Connector> appropriateConnector = this.horizontalCableTray.GetAppropriateConnector(this.verticalCableTray.CableTray);
			Connector connector = appropriateConnector[0];
			Connector connector2 = appropriateConnector[1];
			foreach (Connector connector3 in RevitUtils.GetConduitFittingConnectors(fitting))
			{
				if (connector3.CoordinateSystem.BasisZ.IsAlmostEqualTo(XYZ.BasisZ, 0.01) || connector3.CoordinateSystem.BasisZ.IsAlmostEqualTo(-XYZ.BasisZ, 0.01))
				{
					connector3.ConnectTo(connector2);
				}
				else
				{
					connector3.ConnectTo(connector);
				}
			}
			this.doc.Regenerate();
		}

		private void TranslationElbowFitting(Connector verticalConnector, Connector otherVerticalConnector, FamilyInstance fitting)
		{
			double width = this.horizontalCableTray.CableTray.Width;
			foreach (Connector connector in RevitUtils.GetConduitFittingConnectors(fitting))
			{
				if (connector.CoordinateSystem.BasisZ.IsAlmostEqualTo(XYZ.BasisZ, 0.01) || connector.CoordinateSystem.BasisZ.IsAlmostEqualTo(-XYZ.BasisZ, 0.01))
				{
					XYZ xyz = new XYZ(connector.Origin.X, connector.Origin.Y, verticalConnector.Origin.Z) - verticalConnector.Origin;
					double length = xyz.GetLength();
					if (length == 1E-05)
					{
						break;
					}
					if (length > width)
					{
						throw new MyException("请检查桥架位置");
					}
					if (!otherVerticalConnector.IsConnected)
					{
						this.verticalCableTray.CableTray.Location.Move(xyz);
						this.verticalCableTray = new HYCableTray<CableTray>(this.verticalCableTray.CableTray);
						break;
					}
					throw new MyException("请检查桥架位置");
				}
			}
		}

		private void RotateElbowFitting(Connector horizontalConnector, Connector otherHorizontalConnector, FamilyInstance fitting)
		{
			Connector connector = null;
			XYZ xyz = (otherHorizontalConnector.Origin - horizontalConnector.Origin).Normalize();
			foreach (Connector connector2 in RevitUtils.GetConduitFittingConnectors(fitting))
			{
				if (!connector2.CoordinateSystem.BasisZ.IsAlmostEqualTo(XYZ.BasisZ, 0.01) && !connector2.CoordinateSystem.BasisZ.IsAlmostEqualTo(-XYZ.BasisZ, 0.01))
				{
					connector = connector2;
				}
			}
			if (connector != null)
			{
				double num = connector.CoordinateSystem.BasisZ.AngleOnPlaneTo(xyz, XYZ.BasisZ);
				if (num != 0.0)
				{
					Line line = Line.CreateUnbound((fitting.Location as LocationPoint).Point, XYZ.BasisZ);
					fitting.Location.Rotate(line, num);
				}
			}
		}

		private Document doc;

		private HYCableTray<CableTray> horizontalCableTray;

		private HYCableTray<CableTray> verticalCableTray;
	}
}
